ccR.Cast = {
	AoE =
	function(spell, unit, maxRange, yards) 
		if spell == nil then
			ccR.Error(".CastAoE - [spell] is nil.")
		else
			--	if tonumber(spell) ~= nil then spell = GetSpellInfo(spell) end	
			if unit == nil then ccR.Error(".CastAoE - " .. spell .. ", [unit] is missing."); return end
			if unit ~= nil and not ccR.Unit.Exists(unit) then ccR.Error(".CastAoE - " .. spell .. ", [" .. unit .. "] does not exist."); return end
			if maxRange == nil and unit ~= "player" then ccR.Error(".CastAoE - " .. spell .. ", [maxRange] is missing."); return end
			if maxRange ~= nil and tonumber(maxRange) == nil then ccR.Error(".CastAoE - " .. spell .. ", " .. maxRange .. " is not numeric."); return end
			if yards == nil and unit ~= "player" then ccR.Error(".CastAoE - " .. spell .. "," .. maxRange .. ", [yards] not found"); return end
			if yards ~= nil and tonumber(yards) == nil then ccR.Error(".CastAoE - " .. spell .. "," .. maxRange .. "," .. yards .. " is not numeric."); return end

			if not ccR.Player.Has.Spell(spell) then
				return
			else
				local pX, pY, pZ = ObjectPosition("player")
				if unit == "player" then
					ccR.Cast.Spell(spell)
					if SpellIsTargeting() then CastAtPosition(pX, pY, pZ) end
				else
					if ccR.Spell.Is.Ready(spell) 
					and ccR.Unit.Exists(unit)
					and ccR.Unit.Distance(unit, "player") <= maxRange
					and ccR.Unit.Is.InLineOfSight(unit, "player")
					then 
						local uX, uY, uZ = ObjectPosition(unit)
						local rotation = math.atan2(pY - uY, pX - uX) % (math.pi * 2)
						local vCombatReach = UnitCombatReach(unit)
						local vPlayerDistance = ccR.Unit.Distance(unit, "player")
						local gx, gy, gz
						if vPlayerDistance < 0 then 
							range = yards
							gx, gy, gz =  pX - range * math.cos(rotation), pY - range * math.sin(rotation), pZ
						else
							if vCombatReach < yards then range = 0 else range = vPlayerDistance-vCombatReach end
							gx, gy, gz =  uX - range * math.cos(rotation), uY - range * math.sin(rotation), uZ
						end
						if gx and gy and gz then ccR.Cast.Spell(spell) if SpellIsTargeting() then CastAtPosition(gx, gy, gz) end end
					end
				end
			end
		end
	end,
	AF = {
		Attack = function(spell, unit) if unit == nil then unit = "target" end ccR.Cast.Attack(spell, unit, nil, true) end,
		Spell = function(spell, unit) if unit == nil then unit = "target" end ccR.Cast.Spell(spell, unit, true) end,
		Mass = {
			Debuff = function(spell, limit, range, requiresFacing, debuffRemaining) if unit == nil then unit = "target" end ccR.Cast.Mass.Debuff(spell, limit, range, requiresFacing, debuffRemaining, true) end,
		},
	},
	Attack = 
	function(spell, unit, delay, AlwaysFacing)
		if spell == nil then
			ccR.Error(".Cast.Attack - Spell is nil.")
		else
			if unit == nil then unit = "target" end 
			if AlwaysFacing == nil then AlwaysFacing = false end 
			local vPerformCast = nil 
			if ccR.Unit.Is.Attackable(unit)
			and (not ccR.Var("LoS_CastAttack") or (ccR.Var("LoS_CastAttack") and ccR.Unit.Is.InLineOfSight(unit, "player")))
			and ccR.Spell.CanAttack(spell, unit, true)
			then 
				if type(ccR_CastDelay) == "table" then
					for thisGUID, thisSubTable in pairs(ccR_CastDelay) do 
						if thisGUID == UnitGUID(unit) and thisSubTable[1] == spell then	vPerformCast = false end 
					end	
					if vPerformCast == nil then vPerformCast = true end	
				end 
				if vPerformCast then
					ccR.Cast.Spell(spell, unit, AlwaysFacing) 
					if delay ~= nil then 
						if not ccR_CastDelay then ccR_CastDelay = {} end 
						if tonumber(spell) ~= nil then spell = GetSpellInfo(spell) end	
						ccR_CastDelay[UnitGUID(unit)] = {spell}
					end
				else
					return
				end
			end
		end
	end,
	Debuff = 
	function(spell, unit, AlwaysFacing) 
		if unit == nil then unit = "target" end
		ccR.Cast.Attack(spell, unit, true, AlwaysFacing)
	end,
	Execute = 
	function(spell, unit) 
	end,
	Mass = {
		Debuff = 
		function(spell, limit, range, requiresFacing, debuffRemaining, AlwaysFacing) 
			if limit == nil then limit = # ccR_Enemies_In_Combat end
			if limit == "all" then limit = # ccR_Enemies_In_Combat end
			if range == nil then range = 40 end
			if requiresFacing == nil then requiresFacing = false end
			if UseCastDebuff == nil then UseCastDebuff = true end
			if AlwaysFacing == nil then AlwaysFacing = false end
			--if tonumber(spell) ~= nil then spell = GetSpellInfo(spell) end	
			local vHasDebuff = 0
			for x = 1, # ccR_Enemies_In_Combat do
				local vUnit = ccR_Enemies_In_Combat[x]
				if ccR.Unit.Has.MyDebuff(vUnit, spell) 
				and ccR.Unit.Distance(vUnit, "player") <= range 
				then
					vHasDebuff = vHasDebuff + 1 
				end
			end
			if vHasDebuff < limit then
				for x = 1, # ccR_Enemies_In_Combat do
					local vUnit = ccR_Enemies_In_Combat[x]
					if ccR.Unit.Is.Attackable(vUnit)
					and ccR.Spell.CanAttack(spell, vUnit)
					and ccR.Unit.Distance(vUnit, "player") <= range
					and (	
							not ccR.Unit.Has.MyDebuff(vUnit, spell)
							or
							(debuffRemaining ~= nil and ccR.Unit.Has.MyDebuff(vUnit, spell) and ccR.Unit.MyDebuffDuration(vUnit, spell, "<=", debuffRemaining))
						)
					and (not requiresFacing or (requiresFacing and (ccR.Player.Is.Facing(vUnit) or AlwaysFacing)))
					and not ccR.Unit.Is.Immune.To.All(vUnit)
					and not ccR.Unit.Is.CC(vUnit)
					then
						if UseCastDebuff then 
							if tonumber(spell) ~= nil then spell = GetSpellInfo(spell) end	
							ccR.Cast.Debuff(spell, vUnit, AlwaysFacing) 
						else
							ccR.Cast.Attack(spell, vUnit)
						end
					else
						limit = limit - 1
					end
				end
			end
		end,
		Execute = 
		function(spell, limit, range, requiresFacing) 
			if health == nil then health = 20 end
			if requiresFacing == nil then requiresFacing = false end
			for x = 1, # ccR_Enemies_In_Combat do
				local vUnit = ccR_Enemies_In_Combat[x]
				if ccR.Unit.Is.Attackable(vUnit)
				and ccR.Spell.CanAttack(spell, vUnit)
				and ccR.Unit.Distance(vUnit, "player") <= range
				and ccR.Unit.Health(vUnit) <= health
				and (not requiresFacing or (requiresFacing and ccR.Player.Is.Facing(vUnit)))
				then
					ccR.Cast.Attack(spell, vUnit)
				end
			end
		end,
		Interupt = 
		function(spell, range, requiresFacing) 
		end,
	},
	Spell =
 	function(spell, unit, AlwaysFacing, ignoreIsUsable)
		if FireHack == nil then ccR.Error("FireHack is NOT attached.") return end
		if ccR.Player.Is.Caster() then
			for x = 1, # ccR_Enemies_In_Combat do
				local vUnit = ccR_Enemies_In_Combat[x]	
				if ccR.Unit.Exists(vUnit) and ((ccR.Unit.NPCID(vUnit) == 78238 or ccR.Unit.Name(vUnit) == "Pol" ) or (ccR.Unit.NPCID(vUnit) == 76974 or ccR.Unit.Name(vUnit) == "Franzok" )) then
					if ccR.Unit.Is.Casting(vUnit) and (ccR.Unit.Is.CastingSpell(vUnit, 158093) or ccR.Unit.Is.CastingSpell(vUnit, 160838)) then return end	
					if ccR.Unit.Is.Casting(vUnit) and ccR.Unit.Is.Casting("player") and (ccR.Unit.Cast_Time(vUnit) < ccR.Unit.Cast_Time("player") + 1 ) or (ccR.Unit.Is.Casting(vUnit) and ccR.Unit.Is.Channeling("player") and ccR.Unit.Cast_Time(vUnit) < ccR.Unit.Channel_Time("player") + 1 ) then SpellStopCasting() return end
				end					
			end	
			--[[for x = 1, # ccR_Enemies_In_Combat do
				local vUnit = ccR_Enemies_In_Combat[x]	
				if ccR.Unit.Exists(vUnit) and ((ccR.Unit.NPCID(vUnit) == 78238 or ccR.Unit.Name(vUnit) == "Pol" ) or (ccR.Unit.NPCID(vUnit) == 76974 or ccR.Unit.Name(vUnit) == "Franzok" )) then
					if ccR.Unit.Is.CastingSpell(vUnit, 158093) or ccR.Unit.Is.CastingSpell(vUnit, 160838) then 
						if ccR.Unit.Cast_Time(vUnit) < ccR.Spell.CastTime(spell) then SpellStopCasting() return end
				 	end	
			 	end		
			end]]--
		end
		if AlwaysFacing == nil then AlwaysFacing = false end
		if ignoreIsUsable == nil then ignoreIsUsable = false end
		if spell == nil then
			ccR.Error(".Cast.Spell - [spell] is nil.") 
		else
			if tonumber(spell) ~= nil then spell = GetSpellInfo(spell) end
		 	if not ccR.Player.Has.Spell(spell, ignoreIsUsable)
			or ccR.Player.Is.CastingOrChanneling()
			or (AlwaysFacing and not HasFullControl())
			then 
				return 
			else
				local Facing
				if AlwaysFacing then Facing = ObjectFacing("player") end
			 	if unit ~= nil then
			 		if not ccR.Unit.Exists(unit) then 
			 	 		ccR.Error(".Cast.Spell(" .. spell .. ", [" .. unit .. "] does not exist.") 
			 	 	else
			 	 		if AlwaysFacing 
			 	 		and HasFullControl()
			 	 		then
			 	 			ccR.Auto.Face(unit, "force")
				 	 		CastSpellByName(spell, unit) 
							if ccR.Var("Debug_ShowCast") then ccR.PrintToChat(GetTime() .. " - " .. spell) end
				 	 		FaceDirection(Facing)
			 	 		else
							if ccR.Var("Debug_ShowCast") then ccR.PrintToChat(GetTime() .. " - " .. spell) end
							 if (ccR.Player.Has.Target() or not ccR.Player.Has.Target()) and ccR.Player.Is.Healer() 
							 	and not (ccR.Unit.Class("player") == "Monk" and ccR.Player.Specialization() == 2 and GetShapeshiftForm() == 2 )
						        and ccR.Target.Name() ~= ccR.Unit.Name(unit)
						        then
						        TargetUnit(unit)
						        end
				 	 		CastSpellByName(spell, unit) 
				 	 	end
			 	 	end
			 	else
					if ccR.Var("Debug_ShowCast") then ccR.PrintToChat(GetTime() .. " - " .. spell) end
			 	 	CastSpellByName(spell)
			 	end
			end
		end	
	end,
	SpellStopCasting =
	function(spell, unit, AlwaysFacing)
		if FireHack == nil then ccR.Error("FireHack is NOT attached.") return end
		if AlwaysFacing == nil then AlwaysFacing = false end
		if spell == nil then
			ccR.Error(".Cast.Spell - [spell] is nil.") 
		else
			if tonumber(spell) ~= nil then spell = GetSpellInfo(spell) end
			if not ccR.Player.Has.Spell(spell) 
			or (AlwaysFacing and not HasFullControl())
			then 
				return 
			else
				local Facing
				if AlwaysFacing then Facing = ObjectFacing("player") end
			 	if unit ~= nil then
			 		if not ccR.Unit.Exists(unit) then 
			 	 		ccR.Error(".Cast.Spell(" .. spell .. ", [" .. unit .. "] does not exist.") 
			 	 	else
			 	 		if AlwaysFacing 
			 	 		and HasFullControl()
			 	 		then
			 	 			ccR.Auto.Face(unit, "force")
				 	 		CastSpellByName(spell, unit) 
							if ccR.Var("Debug_ShowCast") then ccR.PrintToChat(GetTime() .. " - " .. spell) end
				 	 		FaceDirection(Facing)
			 	 		else
							if ccR.Var("Debug_ShowCast") then ccR.PrintToChat(GetTime() .. " - " .. spell) end
				 	 		CastSpellByName(spell, unit) 
				 	 	end
			 	 	end
			 	else
					if ccR.Var("Debug_ShowCast") then ccR.PrintToChat(GetTime() .. " - " .. spell) end
			 	 	CastSpellByName(spell)
			 	end
			end
		end	
	end,
}
setmetatable(ccR.Cast, ccR)